/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package genetic;

import java.awt.Point;
import java.util.ArrayList;
import java.util.Collections;
import reader.Data;
import reader.Header;

/**
 *
 * @author Ifun
 */
public class Population {
    ArrayList<Individual> society;
    
    public Population()
    {
        society = new ArrayList<Individual>();
    }
    
    public ArrayList<Individual> getSociety()
    {
        return society;
    }
    
    public Population(int num, int numChrom, Header listAtrib)
    {
        society = new ArrayList<Individual>();
        for(int i=0;i<num;++i)
        {
            Individual person = new Individual(numChrom, listAtrib);
            society.add(person);
        }
    }
    
    public ArrayList<Individual> select(float fraction)
    {
        int num = Math.round(society.size() * (1-fraction));
        ArrayList<Individual> selected = new ArrayList<Individual>();
        ArrayList<Integer> container = new ArrayList<Integer>();
        int i = 0;
        while(selected.size()<num)
        {
            if(genMath.getRandomInt(101)<society.get(i).probability)
            {
                if(!container.contains(i))
                {
                    container.add(i);
                    selected.add(society.get(i));
                }
            }
            ++i;
            if(i==society.size())
            {
                i=0;
            }
        }
        
        return selected;
    }
    
    public ArrayList<Point> pairsIndividual(float fraction)
    {
        ArrayList<Point> pairs = new ArrayList<Point>();
        int num = Math.round(fraction * society.size()/2);
        ArrayList<Integer> container = new ArrayList<Integer>();
        int x = -1;
        int y = -1;
        int i = 0;
        int rand = 0;
        while(pairs.size()<num)
        {
            //System.out.println("11111111111111111");
            while(x==-1)
            {
                //System.out.println("222222222222");
                rand = genMath.getRandomInt(100) + 1;
                if( rand <society.get(i).probability)
                {
                    if(!container.contains(i))
                    {
                        container.add(i);
                        x = i;
                        i=0;
                        while(y==-1)
                        {
                            //System.out.println("333333333333");
                            rand = genMath.getRandomInt(100) + 1;
                            if(rand<society.get(i).probability)
                            {
                                if(!container.contains(i))
                                {
                                    container.add(i);
                                    y=i;
                                    Point p = new Point(x,y);
                                    pairs.add(p);
                                    i=0;
                                }
                            }
                            ++i;
                            if(i==society.size())
                            {
                                i=0;
                            }
                        }
                    }
                }
                ++i;
                if(i==society.size())
                {
                    i=0;
                }
            }
                x = -1;
                y = -1;
        }
              
        return pairs;
    }
    
    public void rankPopulation()
    {
        Collections.sort(society);
    }
    
    public void updateProbability()
    {
        int sumFitness = 0;
        for(int i=0;i<society.size();++i)
        {
            sumFitness += society.get(i).getFitness();
        }
        
        for(int i=0;i<society.size();++i)
        {
            society.get(i).setProbability(sumFitness);
        }
    }
    
    public void updateFitness(Data data) throws Exception
    {
        for(int i=0;i<society.size();++i)
        {
            if(society.get(i).getFitness()==-1)
            {
                society.get(i).calculateFitness(data);
            }
        }
    }
    
    public int mutationPop(int mutRate)
    {
        int mutate = -1;
        int rand = genMath.getRandomInt(100) + 1;
        if(rand<mutRate)
        {
            int mutanNum = genMath.getRandomInt(society.size());
            society.get(mutanNum).mutationIndividual();
            mutate = mutanNum;
        }
        
        return mutate;
    }
    
    public int getMaxFitness()
    {
        int max = 0;
        for(int i=0;i<society.size();++i)
        {
            if(max<society.get(i).getFitness())
            {
                max = society.get(i).getFitness();
            }
        }
        
        return max;
    }
}
